/**
 * Copyright (c) [2025] [AGIROS] 
 * [travoddsgen] is licensed under Mulan PSL v2. 
 * You can use this software according to the terms and conditions of the Mulan PSL v2. 
 * You may obtain a copy of Mulan PSL v2 at: 
 *          http://license.coscl.org.cn/MulanPSL2 
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
 * See the Mulan PSL v2 for more details.
 */ 

#include <iostream>
#include "CppLangGetMaxSerializeSizeVisitor.h"
#include "CLangTypeNameVisitor.h"

CppLangGetMaxSerializeSizeVisitor::CppLangGetMaxSerializeSizeVisitor(CppLangTypeNameVisitor* typeNameVisitor)
    : FileGenVisitor("", ""), typeNameVisitor_(typeNameVisitor), isArray_(false), lengthUnlimited_(false) {
    CLangTypeNameVisitor* clangTypeNameVisitor = dynamic_cast<CLangTypeNameVisitor*>(typeNameVisitor_);
    isCppLangTypeSupport_ = (clangTypeNameVisitor == nullptr);
}

void CppLangGetMaxSerializeSizeVisitor::visit(BaseTypeNode& node) {
    std::string memberTypeName = typeNameVisitor_->findName(memberType_);
    if (isArray_) {
        // 如果是数组类型，调用getBaseTypeArraySize函数
        content_ += indent() + "currentAlignment += AGIDDSCdrSerializer::getBaseTypeArraySize(";
        content_ += "sizeof(" + memberTypeName + ")";
        content_ += ", sizeof(" + memberName_ + ") / sizeof(" + memberTypeName + ")";
        content_ += ", currentAlignment);\n";
        return;
    }
    // 非数组基本数据类型，调用getBaseTypeySize函数
    content_ += indent() + "currentAlignment += AGIDDSCdrSerializer::getBaseTypeSize(";
    content_ += "sizeof(" + memberTypeName;
    content_ += "), currentAlignment);\n";
}

void CppLangGetMaxSerializeSizeVisitor::visit(SequenceTypeNode &node) {
    // 判断是否有上界
    if (!node.size_) {
        // 无界，直接返回LENGTH_UNLIMITED
        lengthUnlimited_ = true;
        return;
    }
    // 序列化vector的长度
    content_ += indent() + "currentAlignment += AGIDDSCdrSerializer::getBaseTypeSize(";
    content_ += "sizeof(uint32_t)";
    content_ += ", currentAlignment);\n";
    // 有界，按照上界计算
    std::string boundStr = typeNameVisitor_->findName(node.size_);
    // 如果elementType是BaseTypeNode，调用serializeBaseTypeArray
    BaseTypeNode *eleType = dynamic_cast<BaseTypeNode *>(node.type_);
    if (eleType) {
        content_ += indent() + "currentAlignment += AGIDDSCdrSerializer::getBaseTypeArraySize(";
        content_ += "sizeof(" + typeNameVisitor_->findName(node.type_);
        content_ += "), + " + boundStr;
        content_ += ", currentAlignment);\n";
        return;
    }
    // 其他情况，循环调用elementType的序列化visitor
    content_ += indent() + "for (size_t i = 0; i < " + boundStr + "; ++i) {\n";
    memberName_ = memberName_ + "[i]";
    ++indentLevel_;
    node.type_->accept(*this);
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangGetMaxSerializeSizeVisitor::visit(StringTypeNode& node) {
    if (!node.size_) {
        // 无界，直接返回LENGTH_UNLIMITED
        lengthUnlimited_ = true;
        return;
    }
    // 有界，按照上界计算
    std::string boundStr = typeNameVisitor_->findName(node.size_);
    content_ += indent() + ("currentAlignment += AGIDDSCdrSerializer::getStringSize(" + boundStr + ", currentAlignment);\n");
}

void CppLangGetMaxSerializeSizeVisitor::visit(WideStringTypeNode& node) {
    if (!node.size_) {
        // 无界，直接返回LENGTH_UNLIMITED
        lengthUnlimited_ = true;
        return;
    }
    // 有界，按照上界计算
    std::string boundStr = typeNameVisitor_->findName(node.size_);
    content_ += indent() + ("currentAlignment += AGIDDSCdrSerializer::getWStringSize(" + boundStr + ", currentAlignment);\n");
}

void CppLangGetMaxSerializeSizeVisitor::visit(FixedPtTypeNode& node) {
    if (node.digits_) {
        node.digits_->accept(*this);
    }
    if (node.scale_) {
        node.scale_->accept(*this);
    }
}

void CppLangGetMaxSerializeSizeVisitor::visit(MapTypeNode& node) {
    // 如果没有size_，直接返回LENGTH_UNLIMITED
    if (!node.size_) {
        lengthUnlimited_ = true;
        return;
    }
    // 序列化map的长度
    content_ += indent() + "currentAlignment += AGIDDSCdrSerializer::getBaseTypeSize(";
    content_ += "sizeof(uint32_t)";
    content_ += ", currentAlignment);\n";
    // 循环map的内容
    if (isCppLangTypeSupport_) {
        content_ += indent() + "for (auto it = " + memberName_ + ".begin(); it != " + memberName_ + ".end(); ++it) {\n";
        ++indentLevel_;
        // 序列化key
        memberName_ = "it->first";
        memberType_ = node.keyType_;
        isArray_ = false;
        if (node.keyType_) {
            node.keyType_->accept(*this);
        }
        // 序列化value
        memberName_ = "it->second";
        memberType_ = node.valueType_;
        isArray_ = false;
        if (node.valueType_) {
            node.valueType_->accept(*this);
        }
        --indentLevel_;
        content_ += indent() + "}\n";
    } else {
        std::string memberTypeName = typeNameVisitor_->findName(&node);
        content_ += indent() + "for (int index = 0; index < ";
        content_ += memberTypeName + "_size(" + memberName_ + "); ";
        content_ += "index++) {\n";
        ++indentLevel_;
        std::string keyTypeName = typeNameVisitor_->findName(node.keyType_);
        std::string valueTypeName = typeNameVisitor_->findName(node.valueType_);
        content_ += indent() + keyTypeName + " *key;\n";
        content_ += indent() + valueTypeName + " *value;\n";
        content_ += indent() + memberTypeName + "_index(" + memberName_ + ", index, &key, &value);\n";
        // 序列化key
        memberName_ = "(*key)";
        memberType_ = node.keyType_;
        isArray_ = false;
        if (node.keyType_) {
            node.keyType_->accept(*this);
        }
        // 序列化value
        memberName_ = "(*value)";
        memberType_ = node.valueType_;
        isArray_ = false;
        if (node.valueType_) {
            node.valueType_->accept(*this);
        }
        --indentLevel_;
        content_ += indent() + "}\n";
    }
}

void CppLangGetMaxSerializeSizeVisitor::visit(StructDefNode& node) {
    // 每次清空content_，重新生成
    content_ = "";
    lengthUnlimitedContent_ = "";
    lengthUnlimited_ = false;
    std::string structName = typeNameVisitor_->findName(&node);
    // 如果已经生成则略过
    if (generatedTypeNames.find(structName) != generatedTypeNames.end()) {
        return;
    }
    generatedTypeNames[structName] = 0;
    bool isNested = (TypeAnnotationNode::getExtensibility(node.annotations_) == TypeAnnotationNode::AnnotationType::MUTABLE);
    plainCdrMode_ = true;
    content_ += "unsigned int " + structName + "TypeSupport::get_max_serialized_data_size(void* data, unsigned int currentAlignment) {\n";
    lengthUnlimitedContent_ = content_;
    lengthUnlimitedContent_ += "    return LENGTH_UNLIMITED;\n";
    lengthUnlimitedContent_ += "}\n\n";
    ++indentLevel_;
    content_ += indent() + structName + "* structData = static_cast<" + structName + "*>(data);\n";
    // 保存初始化对齐值
    content_ += indent() + "unsigned int initialAlignment = currentAlignment;\n";
    content_ += indent() + "unsigned int tmpAlignment = 0;\n";
    if (isNested) {
        // 第一个parameter的对齐
        content_ +=indent() + "currentAlignment += (currentAlignment & 1) == 0 ? 0 : (2 - (currentAlignment & 1));\n";
        plainCdrMode_ = false;
    }
    for (auto &member : node.members_->nodes_) {
        member->accept(*this);
        if (lengthUnlimited_) {
            content_ = lengthUnlimitedContent_;
            return;
        }
    }
    content_ += indent() + "return currentAlignment - initialAlignment;\n";
    --indentLevel_;
    content_ += "}\n\n";
    return;
}

void CppLangGetMaxSerializeSizeVisitor::visit(ScopedNameNode &node) {
    DefinitionNode *eleTypeDcl = typeNameVisitor_->findType(&node);
    TypeDefDclNode* eleTypeDef = dynamic_cast<TypeDefDclNode*>(eleTypeDcl);
    if (eleTypeDef) {
        isArray_ = (eleTypeDef->dims_ != nullptr && eleTypeDef->dims_->nodes_.size() > 0);
        memberType_ = eleTypeDef->refType_;
        eleTypeDef->refType_->accept(*this);
        return;
    }
    EnumDclNode* eleEnum = dynamic_cast<EnumDclNode*>(eleTypeDcl);
    if (eleEnum) {
        eleEnum->accept(*this);
        return;
    }
    std::string memberTypeName = "";
    StructDefNode* eleStruct = dynamic_cast<StructDefNode*>(eleTypeDcl);
    if (eleStruct) {
        memberTypeName = typeNameVisitor_->findName(eleStruct);
    }
    UnionDefNode* eleUnion = dynamic_cast<UnionDefNode*>(eleTypeDcl);
    if (eleUnion) {
        memberTypeName = typeNameVisitor_->findName(eleUnion);
    }
    if (isArray_) {
        content_ += indent() + "for (size_t i = 0; i < sizeof(" + memberName_ + ") / sizeof(" + memberName_ + "[0]); ++i) {\n";
        ++indentLevel_;
        content_ += indent() + "currentAlignment += " + memberTypeName + "TypeSupport::get_instance()->get_max_serialized_data_size(";
        content_ += "&" + memberName_ + "[i]";
        content_ += ", currentAlignment);\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
    // 非u_
    content_ += indent() + "currentAlignment += " + memberTypeName + "TypeSupport::get_instance()->get_max_serialized_data_size(&" + memberName_ + ", currentAlignment);\n";
}

void CppLangGetMaxSerializeSizeVisitor::visitPlCdr(ASTNode* type, const std::string& idStr) {
    // 序列化parameter头，包括id和长度
    content_ += indent() + "currentAlignment += 4;\n";
    content_ += indent() + "tmpAlignment = currentAlignment;\n";
    content_ += indent() + "currentAlignment = 0;\n";
    // 序列化成员
    type->accept(*this);
    // 4字节对齐
    content_ += indent() + "currentAlignment += tmpAlignment;\n";
    content_ += indent() + "currentAlignment += (currentAlignment & 3) == 0 ? 0 : (4 - (currentAlignment & 3));\n";
}

void CppLangGetMaxSerializeSizeVisitor::visit(MemberNode &node) {
    // TODO 先不处理shared成员
    if (node.isShared()) {
        return;
    }
    memberName_ = "structData->" + *node.identifier_;
    memberType_ = node.type_;
    isArray_ = (node.arrayDims_ && node.arrayDims_->nodes_.size() > 0);
    if (plainCdrMode_) {
        node.type_->accept(*this);
        return;
    }
    // PL_CDR模式
    PositiveIntConstNode* id = node.getIdNode();
    if (!id) {
        // mutable类型的成员必须有id
        std::cerr << "Error: mutable member " << *(node.identifier_) << "::" << *(node.identifier_) << " must have id" << std::endl;
        exit(1);
    }
    std::string idStr = typeNameVisitor_->findName(id);
    memberName_ = "structData->" + *node.identifier_;
    visitPlCdr(node.type_, idStr);
}

void CppLangGetMaxSerializeSizeVisitor::visit(ListNode<FixedArraySizeNode *> &node) {
    for (auto &fixedArraySize : node.nodes_) {
        if (fixedArraySize) {
            fixedArraySize->accept(*this);
        }
    }
}

void CppLangGetMaxSerializeSizeVisitor::visit(FixedArraySizeNode& node) {
    if (node.size_) {
        node.size_->accept(*this);
    }
}

void CppLangGetMaxSerializeSizeVisitor::visit(UnionDefNode& node) {
    // 每次清空content_，重新生成
    content_ = "";
    std::string unionName = typeNameVisitor_->findName(&node);
    // 如果已经生成则略过
    if (generatedTypeNames.find(unionName) != generatedTypeNames.end()) {
        return;
    }
    generatedTypeNames[unionName] = 0;
    bool isNested = (TypeAnnotationNode::getExtensibility(node.annotations_) == TypeAnnotationNode::AnnotationType::MUTABLE);
    content_ += "int " + unionName + "TypeSupport::get_max_serialized_data_size(void* data, unsigned int currentAlignment) {\n";
    lengthUnlimitedContent_ = content_;
    lengthUnlimitedContent_ += "    return LENGTH_UNLIMITED;\n";
    lengthUnlimitedContent_ += "}\n\n";
    ++indentLevel_;
    content_ += indent() + unionName + "* structData = static_cast<" + unionName + "*>(data);\n";
    plainCdrMode_ = true;
    if (isNested) {
        // 第一个parameter的对齐
        content_ +=indent() + "currentAlignment += (currentAlignment & 1) == 0 ? 0 : (2 - (currentAlignment & 1));\n";
        plainCdrMode_ = false;
    }
    // 序列化辨别器的值
    memberName_ = "structData->u_";
    isArray_ = false;
    if (plainCdrMode_) {
        if (node.switchType_->type_) {
            memberType_ = node.switchType_->type_;
            node.switchType_->type_->accept(*this);
        } else if (node.switchType_->scopedName_) {
            memberType_ = node.switchType_->scopedName_;
            node.switchType_->scopedName_->accept(*this);
        }
    } else {
        if (node.switchType_->type_) {
            memberType_ = node.switchType_->type_;
            visitPlCdr(node.switchType_->type_, "0");
        } else if (node.switchType_->scopedName_) {
            memberType_ = node.switchType_->scopedName_;
            visitPlCdr(node.switchType_->scopedName_, "0");
        }
    }
    // 根据switch的值序列化不同的内容
    content_ += indent() + "switch(structData->u_) {\n";
    // 序列化cases
    if (node.cases_) {
        node.cases_->accept(*this);
        if (lengthUnlimited_) {
            content_ = lengthUnlimitedContent_;
            return;
        }
    }
    content_ += indent() + "}\n";
    content_ += indent() + "return 0;\n";
    --indentLevel_;
    content_ += "}\n\n";
    return;
}

void CppLangGetMaxSerializeSizeVisitor::visit(CaseNode& node) {
    if (node.labels_) {
        node.labels_->accept(*this);
    }
    ++indentLevel_;
    if (node.members_) {
        node.members_->accept(*this);
    }
    --indentLevel_;
}

void CppLangGetMaxSerializeSizeVisitor::visit(CaseLabelNode& node) {
    if (node.expression_) {
        std::string caseStr = typeNameVisitor_->findName(node.expression_);
        content_ += indent() + "case " + caseStr + ":\n";
    } else {
        content_ += indent() + "default:\n";
    }
}

void CppLangGetMaxSerializeSizeVisitor::visit(EnumDclNode& node) {
    // 调用getBaseTypeSize函数
    std::string bitBound = typeNameVisitor_->getBitbound(node);
    content_ += indent() + "currentAlignment += AGIDDSCdrSerializer::getBaseTypeSize(";
    content_ += bitBound + " / 8";
    content_ += ", currentAlignment);\n";
}
